package xj.graph2d.app.prop;

import java.awt.Color;
import java.util.Comparator;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import xj.graph2d.app.resources.Style;
import xj.graph2d.table.FeatureTable;
import xj.graph2d.table.FeatureTableEntry;
import xj.model.uml.BasicModelElement;
import xj.model.uml.Parameter;

public class UMLParameterEntry implements FeatureTableEntry {

  // position of each column
  public static final int NAME_COLUMN = 0;

  public static final int TYPE_COLUMN = 1;

  public static final int DEFAULT_VALUE_COLUMN = 2;

  public static final int DIRECTION_COLUMN = 3;

  public static final int DELETE_COLUMN = 4;

  public static final String[] columnNames = { "Name", "Type", "Default vaule",
      "Direction", "Delete", };

  public static final String[] columnTips = { "Name of the parameter",
      "Type of the parameter", "Default value of the parameter (optional)",
      "Direction of the parameter (optional)", "Delete the marked parameter", };

  public static final Comparator[] comparators = {
      new FeatureEntryComparator(NAME_COLUMN),
      new FeatureEntryComparator(TYPE_COLUMN),
      new FeatureEntryComparator(DEFAULT_VALUE_COLUMN),
      new FeatureEntryComparator(DIRECTION_COLUMN), null, };

  public static TableCellEditor[] editors = new TableCellEditor[5];
  static {
    JComboBox type = new JComboBox();
    type.addItem("boolean");
    type.addItem("int");
    type.addItem("char");
    type.addItem("byte");
    type.addItem("long");
    type.addItem("short");
    type.addItem("double");
    type.addItem("float");
    type.addItem("Collection");
    type.addItem("List");
    type.addItem("Set");
    type.addItem("Map");
    type.addItem("Object");
    type.addItem("String");
    type.addItem("Date");
    type.addItem("Time");
    type.setEditable(true);
    type.setBackground(Color.white);
    type.setFont(Style.editorFont);
    editors[TYPE_COLUMN] = new DefaultCellEditor(type);

    JComboBox defvalue = new JComboBox();
    defvalue.addItem("0");
    defvalue.addItem("null");
    defvalue.addItem("\"\"");
    defvalue.addItem("false");
    defvalue.addItem("true");
    defvalue.setEditable(true);
    defvalue.setBackground(Color.white);
    defvalue.setFont(Style.editorFont);
    editors[DEFAULT_VALUE_COLUMN] = new DefaultCellEditor(defvalue);

    JComboBox direction = new JComboBox();
    direction.addItem(Parameter.Direction.In);
    direction.addItem(Parameter.Direction.Out);
    direction.addItem(Parameter.Direction.InOut);
    direction.setBackground(Color.white);
    direction.setFont(Style.editorFont);
    editors[DIRECTION_COLUMN] = new DefaultCellEditor(direction);
  }

  public static TableCellRenderer[] renderers = { null, null, null, null,
      new FeatureTable.GrayBooleanRenderer(), // for Delete
  };

  public static final int[] columnWidths = { 50, 50, 50, 50, 20, };

  public UMLParameterEntry(Parameter parameter) {
    this.parameter = parameter;
  }

  public int getColumnCount() {
    return columnNames.length;
  }

  public String getColumnName(int col) {
    if (col >= 0 && col < columnNames.length) {
      return columnNames[col];
    }
    return null;
  }

  public Object getColumnValue(int col) {
    Object result = null;
    if (parameter != null && col >= 0 && col < columnNames.length) {
      switch (col) {
      case NAME_COLUMN:
	result = parameter.getName();
	break;
      case TYPE_COLUMN:
	result = parameter.getType();
	break;
      case DEFAULT_VALUE_COLUMN:
	result = parameter.getDefaultValue();
	break;
      case DIRECTION_COLUMN:
	result = parameter.getDirection();
	break;
      case DELETE_COLUMN:
	result = deleted;
	break;
      }
    }

    // System.out.println("UMLParameterEntry.getColumnValue() col=" + col +
    // " result=" + result);

    return result;
  }

  public void setColumnValue(int col, Object value) {
    // System.out.println("UMLParameterEntry.setColumnValue() col=" + col +
    // " value=" + value);

    if (parameter != null && col >= 0 && col < columnNames.length) {
      switch (col) {
      case NAME_COLUMN:
	if (value != null) {
	  parameter.setName(value.toString());
	} else {
	  parameter.setName(null);
	}
	break;
      case TYPE_COLUMN:
	if (value != null) {
	  parameter.setType(value.toString());
	} else {
	  parameter.setType(null);
	}
	break;
      case DEFAULT_VALUE_COLUMN:
	if (value != null) {
	  parameter.setDefaultValue(value.toString());
	} else {
	  parameter.setDefaultValue(null);
	}
	break;
      case DIRECTION_COLUMN:
	if (value instanceof Parameter.Direction) {
	  parameter.setDirection((Parameter.Direction) value);
	}
	break;
      case DELETE_COLUMN:
	if (value instanceof Boolean) {
	  deleted = ((Boolean) value).booleanValue();
	}
	break;
      }
    }
  }

  public String getColumnTip(int col) {
    if (col >= 0 && col < columnTips.length) {
      return columnTips[col];
    }
    return null;
  }

  public Class getColumnClass(int col) {
    switch (col) {
    case NAME_COLUMN:
      return String.class;
    case TYPE_COLUMN:
      return String.class;
    case DEFAULT_VALUE_COLUMN:
      return Object.class;
    case DIRECTION_COLUMN:
      return Parameter.Direction.class;
    case DELETE_COLUMN:
      return Boolean.class;
    default:
      return String.class;
    }
  }

  public Comparator getColumnComparator(int col) {
    if (col >= 0 && col < comparators.length) {
      return comparators[col];
    }
    return null;
  }

  public TableCellEditor getColumnEditor(int col) {
    if (col >= 0 && col < editors.length) {
      return editors[col];
    }
    return null;
  }

  public boolean isColumnEditable(int col) {
    if (col >= 0 && col < columnNames.length) {
      return true;
    }
    return false;
  }

  public TableCellRenderer getColumnRenderer(int col) {
    if (col >= 0 && col < renderers.length) {
      return renderers[col];
    }
    return null;
  }

  public int getColumnWidth(int col) {
    if (col >= 0 && col < columnWidths.length) {
      return columnWidths[col];
    }
    return -1;
  }

  public Parameter getParameter() {
    return parameter;
  }

  public String getName() {
    if (parameter != null) {
      return parameter.getName();
    }
    return null;
  }

  public BasicModelElement getModelElement() {
    return parameter;
  }

  public boolean isDeleted() {
    return deleted;
  }

  public boolean isEditable() {
    return true;
  }

  protected Parameter parameter;

  protected boolean deleted;

  static public class FeatureEntryComparator implements Comparator {

    public FeatureEntryComparator(int col) {
      this.col = col;
    }

    public int compare(Object o1, Object o2) {
      if (o1 instanceof UMLParameterEntry && o2 instanceof UMLParameterEntry) {
	UMLParameterEntry e1 = (UMLParameterEntry) o1;
	UMLParameterEntry e2 = (UMLParameterEntry) o2;
	Object v1 = e1.getColumnValue(col);
	Object v2 = e2.getColumnValue(col);
	if (v1 != null && v2 != null) {
	  switch (col) {
	  case DEFAULT_VALUE_COLUMN:
	    return (v1.toString()).compareTo(v2.toString());
	  case DIRECTION_COLUMN:
	    return ((Parameter.Direction) v1)
		.compareTo((Parameter.Direction) v2);
	  default:
	    return ((String) v1).compareTo((String) v2);
	  }
	}
      }
      return 0;
    }

    protected int col;
  }

}
